/*
	Copyright (c) 2011 Canadensys
*/
package net.canadensys.dataportal.vascan.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.logging.Logger;
import java.util.concurrent.TimeUnit;
import java.text.ParseException;

import net.canadensys.dataportal.utils.HibernateUtil;
import net.canadensys.dataportal.vascan.Taxon;
import net.canadensys.dataportal.vascan.TaxonManager;
import net.canadensys.dataportal.vascan.config.ApplicationConfig;
import net.canadensys.dataportal.vascan.config.ConfigManager;
import net.canadensys.dataportal.vascan.config.impl.InstallationConfig;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.hibernate.Session;

/**
 * This servlet is used to download a generated image from the server disk.
 * The image must reside in the InstallationConfig.GENERATED_IMAGES_DIR folder.
 * We do not serve images statically because we do not keep them on the server. 
 */
public class GetImageServlet extends HttpServlet {
	
	private static final long serialVersionUID = -8731334490437458473L;
	private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
	private static final long DAY_MS = TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS); //gives 86400000
	private static final String PNG_MIME_TYPE = "image/png";
	private static final String SVG_MIME_TYPE = "image/svg+xml";
	private static final String DOWNLOAD_PARAM = "download";
	
	public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { 
		
		String fileName = req.getParameter("q");
		String action = req.getParameter("a");
		boolean download = false;
		
		if(fileName == null || fileName.equals("")){
			return;
		}
		//the user can ask for download
		if(action != null && action.equalsIgnoreCase(DOWNLOAD_PARAM)){
			download = true;
		}
		
		//make sure to keep only the file name
		fileName = FilenameUtils.getName(fileName);
		
		String generatedContentPath = InstallationConfig.getInstance().get(InstallationConfig.GENERATED_IMAGES_DIR_KEY);
		File wantedImage = new File(generatedContentPath + fileName);
		boolean imageFound = false;
		if(wantedImage.exists()){
			try{
				Session hibernateSession = HibernateUtil.getSessionFactory().getCurrentSession();
				hibernateSession.beginTransaction();
				//check when the data were last published
				String lastPublicationDate = ConfigManager.loadValueFromDB(ApplicationConfig.CONFIG_KEY_LAST_PUBLICATION_DATE);
				hibernateSession.getTransaction().commit();
				//compare with lastPublicationDate + 1 day because we don't keep the exact time (for the moment)
				if(wantedImage.lastModified() < (DATE_FORMATTER.parse(lastPublicationDate).getTime()+DAY_MS)){
					imageFound = recreateDistributionImage(fileName);
				}
				else{
					imageFound = true;
				}
			}
			catch (ParseException e) {}
		}
		else{
			imageFound = recreateDistributionImage(fileName);
		}
		
		if(!imageFound){
			res.sendError(HttpServletResponse.SC_NOT_FOUND, fileName + " image not found");
			return;
		}
		
		try{
			FileInputStream istrm = new FileInputStream(wantedImage);
			//we need to use getExtension on the config to remove the "."
			if(FilenameUtils.getExtension(ApplicationConfig.PNG_FILE_EXT).equalsIgnoreCase(FilenameUtils.getExtension(fileName))){
				res.setContentType (PNG_MIME_TYPE);
			}
			else if(FilenameUtils.getExtension(ApplicationConfig.SVG_FILE_EXT).equalsIgnoreCase(FilenameUtils.getExtension(fileName))){
				res.setContentType (SVG_MIME_TYPE);
			}
			else{
				res.getWriter().write(fileName + " unknown extension");
				return;
			}
			
			if(download){
				res.setHeader ("Content-Disposition", "attachment; filename=\""+fileName+"\"");
			}
			int byteCopied = IOUtils.copy(istrm, res.getOutputStream());
			res.setContentLength(byteCopied);
		}
		catch(IOException ioEx){
			Logger.getLogger(getClass().getName()).severe("Error while trying to get file " + wantedImage.getAbsolutePath());
		}
	}
	
	/**
	 * Recrete a image (svg and png) from the taxon id extracted from the imgName.
	 * @param imgName
	 * @return
	 */
	private static boolean recreateDistributionImage(String imgName){
		int prefixIdx = imgName.indexOf(ApplicationConfig.SVG_FILE_PREFIX);
		int dotIdx = imgName.lastIndexOf(".");
		if((prefixIdx == 0) && (dotIdx > ApplicationConfig.SVG_FILE_PREFIX.length())){
			String taxonIdStr = imgName.substring(prefixIdx+ApplicationConfig.SVG_FILE_PREFIX.length(), dotIdx);
			try{
				Integer taxonId = Integer.parseInt(taxonIdStr);
				Session hibernateSession = HibernateUtil.getSessionFactory().getCurrentSession();
				hibernateSession.beginTransaction();
				Taxon taxon = (Taxon) hibernateSession.load(Taxon.class, taxonId);
				TaxonManager.writeDistributionSvg(taxon);
				hibernateSession.getTransaction().commit();
				return true;
			}
			catch(org.hibernate.ObjectNotFoundException e){}
			catch (Exception e) {}
		}
		return false;
	}
}
